using System;
using System.Collections.Generic;
using System.ComponentModel;
using UnityEngine;
using UnityGameFramework.Runtime;

namespace LS
{
    [AddComponentMenu("Lancer Studio/Framework")]
    public partial class LSEntry : MonoBehaviour
    {
        private static readonly Dictionary<Type, ComponentReference> s_NativeComponentTypeMap = new Dictionary<Type, ComponentReference>();

        private static LSEntry s_Instance = null;

        public static bool Avalible
        {
            get
            {
                return s_Instance != null;
            }
        }

        /// <summary>
        /// 获取游戏基础组件。
        /// </summary>
        public static BaseComponent Base => GetNativeGFComponent<BaseComponent>();

        /// <summary>
        /// 获取配置组件。
        /// </summary>
        public static ConfigComponent Config => GetNativeGFComponent<ConfigComponent>();

        /// <summary>
        /// 获取数据结点组件。
        /// </summary>
        public static DataNodeComponent DataNode => GetNativeGFComponent<DataNodeComponent>();

        /// <summary>
        /// 获取数据表组件。
        /// </summary>
        public static DataTableComponent DataTable => GetNativeGFComponent<DataTableComponent>();

        /// <summary>
        /// 获取调试组件。
        /// </summary>
        public static DebuggerComponent Debugger => GetNativeGFComponent<DebuggerComponent>();

        /// <summary>
        /// 获取下载组件。
        /// </summary>
        public static DownloadComponent Download => GetNativeGFComponent<DownloadComponent>();

        /// <summary>
        /// 获取实体组件。
        /// </summary>
        public static EntityComponent Entity => GetNativeGFComponent<EntityComponent>();

        /// <summary>
        /// 获取事件组件。
        /// </summary>
        public static EventComponent Event => GetNativeGFComponent<EventComponent>();

        /// <summary>
        /// 获取文件系统组件。
        /// </summary>
        public static FileSystemComponent FileSystem => GetNativeGFComponent<FileSystemComponent>();

        /// <summary>
        /// 获取有限状态机组件。
        /// </summary>
        public static FsmComponent Fsm => GetNativeGFComponent<FsmComponent>();

        /// <summary>
        /// 获取本地化组件。
        /// </summary>
        public static LocalizationComponent Localization => GetNativeGFComponent<LocalizationComponent>();

        /// <summary>
        /// 获取网络组件。
        /// </summary>
        public static NetworkComponent Network => GetNativeGFComponent<NetworkComponent>();

        /// <summary>
        /// 获取对象池组件。
        /// </summary>
        public static ObjectPoolComponent ObjectPool => GetNativeGFComponent<ObjectPoolComponent>();

        /// <summary>
        /// 获取流程组件。
        /// </summary>
        public static ProcedureComponent Procedure => GetNativeGFComponent<ProcedureComponent>();

        /// <summary>
        /// 获取资源组件。
        /// </summary>
        public static ResourceComponent Resource => GetNativeGFComponent<ResourceComponent>();

        /// <summary>
        /// 获取场景组件。
        /// </summary>
        public static SceneComponent Scene => GetNativeGFComponent<SceneComponent>();

        /// <summary>
        /// 获取配置组件。
        /// </summary>
        public static SettingComponent Setting => GetNativeGFComponent<SettingComponent>();

        /// <summary>
        /// 获取声音组件。
        /// </summary>
        public static SoundComponent Sound => GetNativeGFComponent<SoundComponent>();

        /// <summary>
        /// 获取界面组件。
        /// </summary>
        public static UIComponent UI => GetNativeGFComponent<UIComponent>();

        /// <summary>
        /// 获取网络组件。
        /// </summary>
        public static WebRequestComponent WebRequest => GetNativeGFComponent<WebRequestComponent>();

        public static T GetNativeGFComponent<T>()where T: GameFrameworkComponent
        {
            return GetNativeGFComponent(typeof(T)) as T;
        }

        private void Awake()
        {
            if (s_Instance != null)
                DestroyImmediate(gameObject);
            else
                s_Instance = this;
        }

        public static GameFrameworkComponent GetNativeGFComponent(Type componentType)
        {
            if (s_NativeComponentTypeMap.TryGetValue(componentType,out var componentRef))
            {
                return componentRef.Component;
            }

            var gfc = GameEntry.GetComponent(componentType);
            if(gfc != null)
            {
                componentRef = new ComponentReference(gfc);
                s_NativeComponentTypeMap.Add(componentType, componentRef);
            }
            return gfc;
        }

        public static T GetGFComponent<T>(Type componentType) where T : GameFrameworkComponent
        {
            return GetGFComponent(typeof(T)) as T;
        }
        
        public static GameFrameworkComponent GetGFComponent(Type componentType)
        {
            if(componentType.IsAssignableFrom(typeof(NativeGameFrameworkComponent)))
            {
                return GetNativeGFComponent(componentType);
            }
            else
            {
                return GetCustomGFComponent(componentType);
            }
        }
        
        internal class ComponentReference
        {
            private GameFrameworkComponent m_ComponentReference;

            public bool IsFound => m_ComponentReference != null;
            public GameFrameworkComponent Component => m_ComponentReference;

            public ComponentReference() 
            {
                
            }

            public ComponentReference(GameFrameworkComponent component)
            {
                m_ComponentReference = component;
            }
        }
    }
}
